package com.by.basicgateway.security;

import com.alibaba.fastjson2.JSON;
import com.by.basicgateway.dto.ByGatewayAuthentication;
import com.by.basicgateway.enums.RequestorClientTypeEnum;
import com.by.basicgateway.exception.ByAuthenticationServiceException;
import com.by.gatewayhelper.token.TokenHelper;
import com.by.toolkit.enums.ErrorCodeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Primary;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.Map;

@Slf4j
@Primary
@Component
public class UserAuthenticationManager implements ReactiveAuthenticationManager {

    @Autowired
    @Lazy
    @Qualifier("adminTokenHelper")
    private TokenHelper adminTokenHelper;

    @Autowired
    @Lazy
    @Qualifier("tocTokenHelper")
    private TokenHelper tocTokenHelper;

    @Autowired
    @Lazy
    @Qualifier("wxcpsidebarTokenHelper")
    private TokenHelper wxcpsidebarTokenHelper;

    @Override
    public Mono<Authentication> authenticate(Authentication authentication) {
        log.info("[UserAuthenticationManager][authenticate] 用户认证信息:[{}]", JSON.toJSONString(authentication));
        ByGatewayAuthentication byGatewayAuthentication = (ByGatewayAuthentication) authentication;
        String token = byGatewayAuthentication.getCredentials();
        if (StringUtils.isEmpty(token)) {
            log.info("[UserAuthenticationManager][authenticate] token信息不存在");
            authentication.setAuthenticated(Boolean.FALSE);
            throw new ByAuthenticationServiceException(ErrorCodeEnum.TOKEN_NOT_EXIST.getErrorMessage(), ErrorCodeEnum.TOKEN_NOT_EXIST);
        }
        Map<String, String> details = byGatewayAuthentication.getDetails();
        String clientHeaderValue = details.get("clientHeaderValue");

        RequestorClientTypeEnum requestorClientTypeEnum = RequestorClientTypeEnum.resolveRequestorClientTypeEnum(clientHeaderValue);

        TokenHelper tokenHelper = RequestorClientTypeEnum.TOB_CLIENT.equals(requestorClientTypeEnum)
                ? adminTokenHelper
                : RequestorClientTypeEnum.TOC_CLIENT.equals(requestorClientTypeEnum)
                ? tocTokenHelper
                : wxcpsidebarTokenHelper;

        boolean verifyToken = tokenHelper.verifyToken(token);
        if (verifyToken) {
            authentication.setAuthenticated(Boolean.TRUE);
            return Mono.just(authentication);
        }
        log.info("[UserAuthenticationManager][authenticate] 认证失败");
        authentication.setAuthenticated(Boolean.FALSE);
        throw new ByAuthenticationServiceException(ErrorCodeEnum.SIGNATURE_ERROR_TYPE.getErrorMessage(), ErrorCodeEnum.SIGNATURE_ERROR_TYPE);
    }

}
